"""
性能监控器

监控系统运行性能，包括CPU、内存、处理时间等指标
"""

import time
import psutil
import threading
from typing import Dict, List, Optional, Callable
from loguru import logger
from collections import deque
import numpy as np


class PerformanceMonitor:
    """性能监控器"""
    
    def __init__(self, 
                 enabled: bool = True,
                 sample_interval: float = 1.0,
                 metrics: Optional[List[str]] = None,
                 max_history: int = 1000):
        """
        初始化性能监控器
        
        Args:
            enabled: 是否启用监控
            sample_interval: 采样间隔(秒)
            metrics: 监控指标列表
            max_history: 最大历史记录数
        """
        self.enabled = enabled
        self.sample_interval = sample_interval
        self.max_history = max_history
        
        if metrics is None:
            metrics = ['cpu_usage', 'memory_usage', 'processing_time']
        
        self.metrics = metrics
        
        # 性能数据存储
        self.performance_data = {metric: deque(maxlen=max_history) for metric in metrics}
        self.timestamps = deque(maxlen=max_history)
        
        # 监控线程
        self.monitoring_thread = None
        self.is_monitoring = False
        
        # 回调函数
        self.callbacks = []
        
        # 阈值设置
        self.thresholds = {
            'max_processing_time': 0.1,
            'min_accuracy': 0.8,
            'max_memory_usage': 0.8,
            'max_cpu_usage': 0.9
        }
        
        logger.info("性能监控器初始化完成")
    
    def start_monitoring(self):
        """开始监控"""
        if not self.enabled or self.is_monitoring:
            return
        
        self.is_monitoring = True
        self.monitoring_thread = threading.Thread(target=self._monitoring_loop, daemon=True)
        self.monitoring_thread.start()
        logger.info("性能监控已启动")
    
    def stop_monitoring(self):
        """停止监控"""
        self.is_monitoring = False
        if self.monitoring_thread:
            self.monitoring_thread.join(timeout=5)
        logger.info("性能监控已停止")
    
    def _monitoring_loop(self):
        """监控循环"""
        while self.is_monitoring:
            try:
                # 收集性能数据
                current_data = self._collect_metrics()
                current_time = time.time()
                
                # 存储数据
                for metric, value in current_data.items():
                    self.performance_data[metric].append(value)
                self.timestamps.append(current_time)
                
                # 检查阈值
                self._check_thresholds(current_data)
                
                # 执行回调
                self._execute_callbacks(current_data)
                
                # 等待下次采样
                time.sleep(self.sample_interval)
                
            except Exception as e:
                logger.error(f"性能监控错误: {e}")
                time.sleep(self.sample_interval)
    
    def _collect_metrics(self) -> Dict[str, float]:
        """收集性能指标"""
        metrics = {}
        
        for metric in self.metrics:
            if metric == 'cpu_usage':
                metrics[metric] = psutil.cpu_percent(interval=0.1)
            elif metric == 'memory_usage':
                memory = psutil.virtual_memory()
                metrics[metric] = memory.percent / 100.0
            elif metric == 'processing_time':
                # 这个指标需要外部设置
                metrics[metric] = getattr(self, '_last_processing_time', 0.0)
            elif metric == 'accuracy':
                # 这个指标需要外部设置
                metrics[metric] = getattr(self, '_last_accuracy', 0.0)
            else:
                metrics[metric] = 0.0
        
        return metrics
    
    def _check_thresholds(self, current_data: Dict[str, float]):
        """检查阈值"""
        for metric, value in current_data.items():
            threshold_key = f'max_{metric}' if metric != 'accuracy' else f'min_{metric}'
            
            if threshold_key in self.thresholds:
                threshold = self.thresholds[threshold_key]
                
                if metric == 'accuracy':
                    if value < threshold:
                        logger.warning(f"性能警告: {metric} = {value:.3f} < {threshold}")
                else:
                    if value > threshold:
                        logger.warning(f"性能警告: {metric} = {value:.3f} > {threshold}")
    
    def _execute_callbacks(self, current_data: Dict[str, float]):
        """执行回调函数"""
        for callback in self.callbacks:
            try:
                callback(current_data)
            except Exception as e:
                logger.error(f"回调函数执行失败: {e}")
    
    def add_callback(self, callback: Callable[[Dict[str, float]], None]):
        """
        添加回调函数
        
        Args:
            callback: 回调函数，接收性能数据字典作为参数
        """
        self.callbacks.append(callback)
    
    def remove_callback(self, callback: Callable[[Dict[str, float]], None]):
        """
        移除回调函数
        
        Args:
            callback: 要移除的回调函数
        """
        if callback in self.callbacks:
            self.callbacks.remove(callback)
    
    def set_processing_time(self, processing_time: float):
        """
        设置处理时间
        
        Args:
            processing_time: 处理时间(秒)
        """
        self._last_processing_time = processing_time
    
    def set_accuracy(self, accuracy: float):
        """
        设置准确率
        
        Args:
            accuracy: 准确率(0-1)
        """
        self._last_accuracy = accuracy
    
    def get_current_metrics(self) -> Dict[str, float]:
        """
        获取当前性能指标
        
        Returns:
            当前性能指标字典
        """
        return self._collect_metrics()
    
    def get_metric_history(self, metric: str) -> List[float]:
        """
        获取指标历史数据
        
        Args:
            metric: 指标名称
            
        Returns:
            历史数据列表
        """
        return list(self.performance_data.get(metric, []))
    
    def get_timestamps(self) -> List[float]:
        """
        获取时间戳列表
        
        Returns:
            时间戳列表
        """
        return list(self.timestamps)
    
    def get_statistics(self, metric: str) -> Dict[str, float]:
        """
        获取指标统计信息
        
        Args:
            metric: 指标名称
            
        Returns:
            统计信息字典
        """
        data = self.get_metric_history(metric)
        if not data:
            return {}
        
        return {
            'mean': np.mean(data),
            'std': np.std(data),
            'min': np.min(data),
            'max': np.max(data),
            'median': np.median(data),
            'count': len(data)
        }
    
    def get_all_statistics(self) -> Dict[str, Dict[str, float]]:
        """
        获取所有指标的统计信息
        
        Returns:
            所有指标统计信息字典
        """
        stats = {}
        for metric in self.metrics:
            stats[metric] = self.get_statistics(metric)
        return stats
    
    def set_threshold(self, metric: str, threshold: float):
        """
        设置阈值
        
        Args:
            metric: 指标名称
            threshold: 阈值
        """
        if metric == 'accuracy':
            self.thresholds[f'min_{metric}'] = threshold
        else:
            self.thresholds[f'max_{metric}'] = threshold
    
    def get_thresholds(self) -> Dict[str, float]:
        """
        获取所有阈值
        
        Returns:
            阈值字典
        """
        return self.thresholds.copy()
    
    def clear_history(self):
        """清除历史数据"""
        for metric in self.metrics:
            self.performance_data[metric].clear()
        self.timestamps.clear()
        logger.info("性能历史数据已清除")
    
    def export_data(self, filepath: str):
        """
        导出性能数据
        
        Args:
            filepath: 导出文件路径
        """
        try:
            import json
            
            export_data = {
                'timestamps': list(self.timestamps),
                'metrics': {}
            }
            
            for metric in self.metrics:
                export_data['metrics'][metric] = list(self.performance_data[metric])
            
            with open(filepath, 'w', encoding='utf-8') as f:
                json.dump(export_data, f, indent=2)
            
            logger.info(f"性能数据已导出到: {filepath}")
            
        except Exception as e:
            logger.error(f"性能数据导出失败: {e}")
    
    def get_system_info(self) -> Dict:
        """
        获取系统信息
        
        Returns:
            系统信息字典
        """
        info = {
            'enabled': self.enabled,
            'is_monitoring': self.is_monitoring,
            'sample_interval': self.sample_interval,
            'metrics': self.metrics,
            'max_history': self.max_history,
            'thresholds': self.thresholds,
            'current_data': self.get_current_metrics(),
            'statistics': self.get_all_statistics()
        }
        
        return info
    
    def __enter__(self):
        """上下文管理器入口"""
        self.start_monitoring()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        """上下文管理器出口"""
        self.stop_monitoring()
    
    def __str__(self) -> str:
        status = "运行中" if self.is_monitoring else "已停止"
        return f"PerformanceMonitor(enabled={self.enabled}, status={status})"
    
    def __repr__(self) -> str:
        return self.__str__() 